package com.sktlab.bizconfmobile.model.manager;

import java.text.Collator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

import android.content.Context;
import android.database.Cursor;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds;
import android.util.SparseArray;

import com.sktlab.bizconfmobile.activity.AppClass;
import com.sktlab.bizconfmobile.model.ContactItem;
import com.sktlab.bizconfmobile.model.Participant;
import com.sktlab.bizconfmobile.util.Util;

/**
 * This class is a manager of information about contacts
 * @author wenjuan.li
 *
 */
public class ContactManager {
	
	private static class InstanceHolder {

		private final static ContactManager instance = new ContactManager();
	}
	
	//all contacts, this collection's element contains all information about a contact
	private ArrayList<ContactItem> mAllContacts;	
	//all contact info selected by user,its element only contains the user selected information
	private ArrayList<Participant> mSelectedContacts;
	//a map from contact id to contact object
	private SparseArray<ContactItem> Id2Contact;
	
	private Participant mCurrentUser = null;
	private ContactManager() {
		
		mAllContacts = new ArrayList<ContactItem>();
		mSelectedContacts = new ArrayList<Participant>();
		Id2Contact = new SparseArray<ContactItem>();
		mCurrentUser = new Participant();
	}

	public void Load() {
		
		clear();
		
		loadAllContacts(AppClass.getInstance());
		rmNoNumberContact();
		sortAllContacts();
	}
	
	/**
	 * 
	 */
	public void reset(){
		
		clear();
	}
	
	public void clearSelectedParties() {
		
		if (!Util.isEmpty(mSelectedContacts)) {
			
			for(Participant item : mSelectedContacts) {
				
				int conatactId = item.getContactId();
				int selectedAttrPos = item.getSelectedAttrPosInContactItem();
				
				ContactItem contact = getContactById(conatactId);
				
				if (!Util.isEmpty(contact)) {
					
					contact.setAttrSelectedState(selectedAttrPos, false);
				}			
			}
			
			mSelectedContacts.clear();
		}
	}
	
	public void clear() {
		
		clearSelectedParties();
		
		if (!Util.isEmpty(mAllContacts)) {

			mAllContacts.clear();
		}

		if (!Util.isEmpty(Id2Contact)) {

			Id2Contact.clear();
		}
	}
	
	public static ContactManager getInstance() {
		return InstanceHolder.instance;
	}
	
	public Participant getCurrentUserObject() {
		
		boolean isGuest = Util.isEmpty(CommunicationManager.getInstance().getActiveAccount().getModeratorPw());
		
		if (isGuest) {
			
			mCurrentUser.setName("guestUser");
			mCurrentUser.setIsModerator(false);
		}else {
			
			mCurrentUser.setName("moderator");
			mCurrentUser.setIsModerator(true);
		}
		
		mCurrentUser.setPhone(CommunicationManager.getInstance().getActiveAccount().getDialOutNumber());
				
		return mCurrentUser;
	}
	
	public ContactItem getContactById(int contactId) {
		
		return Id2Contact.get(contactId);
	}
	
	public ArrayList<ContactItem> getAllContacts() {
		return mAllContacts;
	}

	public void setAllContacts(ArrayList<ContactItem> mAllContacts) {
		this.mAllContacts = mAllContacts;
	}
	
	public Participant getSelectedContactByPhoneNum(String phoneNumber) {
		
		Participant part = null;
		
		for (Participant party: mSelectedContacts) {
			
			//if (party.getPhone().equalsIgnoreCase(phoneNumber)) {
			if (phoneNumber.contains(party.getPhone())){	
				part = party;
				break;
			}
		}		
		
		return part;
		
	}
	
	public Participant getSelectedContactByIndex(int index) {
		
		Participant part = null;
		
		if(isIndexValid(index)){
			
			part = mSelectedContacts.get(index);
		}
		
		return part;
	}
	
	public boolean isIndexValid(int index) {
		
		if(index < 0 || index > mSelectedContacts.size()) {
			
			return false;
		}
		
		return true;
	}
	
	/**
	 * add a selected contact
	 * @param participant
	 */
	public void addSelectedContact(Participant participant){
		
		if(!mSelectedContacts.contains(participant)) {
			
			mSelectedContacts.add(participant);
		}		
	}
	
	public void removeSelectedContact(Participant participant) {
		
		if(mSelectedContacts.contains(participant)) {
			
			mSelectedContacts.remove(participant);
		}		
	}
	
	public ArrayList<Participant> getAllSelectedContacts() {
		
		return mSelectedContacts;
	}
	
	private void sortAllContacts() {

		@SuppressWarnings("rawtypes")
		final Comparator cmp = Collator.getInstance(java.util.Locale.CHINA);

		@SuppressWarnings("unchecked")
		Comparator<ContactItem> comparator = new Comparator<ContactItem>() {
			@Override
			public int compare(ContactItem entry1, ContactItem entry2) {
				return cmp.compare(entry1.getSortKey(), entry2.getSortKey());
			}
		};

		Collections.sort(mAllContacts, comparator);	
	}

	private ArrayList<ContactItem> rmNoNumberContact() {

		Cursor contactCursor = AppClass.getInstance().getContentResolver().query(
				ContactsContract.Contacts.CONTENT_URI, null, null, null, null);

		while (contactCursor.moveToNext()) {

			int hasNumber = contactCursor
					.getInt(contactCursor
							.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER));
			int id = contactCursor.getInt(contactCursor
					.getColumnIndex(ContactsContract.Contacts._ID));

			String sortKey = contactCursor
					.getString(contactCursor
							.getColumnIndex(ContactsContract.Contacts.SORT_KEY_PRIMARY));

			if (hasNumber == 0) {

				Id2Contact.remove(id);
			} else {

				ContactItem person = Id2Contact.get(id);
				person.setSortKey(sortKey);
				person.setId(id);
				
				if (person != null) {
					
					person.initSelectedState();
					mAllContacts.add(person);
				}
			}
		};

		if (contactCursor != null) {

			contactCursor.close();
		}
		return mAllContacts;
	}

	private void loadAllContacts(Context ctx) {
		Cursor cursor = ctx.getContentResolver().query(
				ContactsContract.Data.CONTENT_URI, null, null, null, null);

		while (cursor.moveToNext()) {

			int id = cursor.getInt(cursor
					.getColumnIndex(ContactsContract.Data.CONTACT_ID));
			String info = cursor.getString(cursor
					.getColumnIndex(ContactsContract.Data.DATA1));
			String mimeType = cursor.getString(cursor
					.getColumnIndex(ContactsContract.Data.MIMETYPE));

			ContactItem person = null;

			if (Id2Contact.get(id) != null) {

				person = Id2Contact.get(id);
			} else {

				person = new ContactItem();
				Id2Contact.put(id, person);
			}

			if (mimeType.equals(CommonDataKinds.Email.CONTENT_ITEM_TYPE)) {
				person.addEmail(info);

			} else if (mimeType
					.equals(CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE)) {
				person.setAddress(info);
			} else if (mimeType.equals(CommonDataKinds.Phone.CONTENT_ITEM_TYPE)) {
				person.addPhone(info);
			} else if (mimeType
					.equals(CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)) {
				person.setName(info);
			}
		}

		if (cursor != null) {

			cursor.close();
		}
	}
}
